import React from 'react';
import { AudioRecorder } from 'react-native-audio';
import AliyunOSS from 'aliyun-oss-react-native';
import RNFS from 'react-native-fs';

import { Dispatch, State } from './types';
import { loading, modalClose, modalOpen, toolTipOpen } from '../../util/global';
import SelectPic from '../../components/SelectPic';
import { AppApi } from '../../api';
import { isIOS } from '../../constant';
import PortraitAlert from '../../components/Alert/PortraitAlert';

let dispatch: Dispatch;
let state: State;

const audioPath = `${
  isIOS ? RNFS.DocumentDirectoryPath : RNFS.ExternalDirectoryPath
}/videos/test.aac`;

const MAX_TRY_UPLOAD_TIME = 3;
let tryUploadTime = 0;
let isUpload = false;
let onAudioUploaded = (url: string) => {};

export default (d: Dispatch, s: State): void => {
  dispatch = d;
  state = s;
};

export const setShowRecord = (value: boolean): void => {
  dispatch({ type: 'SET_SHOW_RECORD', value });
};

export const setRecording = (value: boolean): void => {
  dispatch({ type: 'SET_RECORDING', value });
};

export const setRecordDuration = (value: number): void => {
  dispatch({ type: 'SET_RECORD_DURATION', value });
};

export const fetchFailed = (): void => {
  dispatch({ type: 'FETCH_FAILED' });
};

export const setOnAudioUploaded = (fn: (url: string) => void): void => {
  onAudioUploaded = fn;
};

export const selectPic = (cb: (url: string) => void): void => {
  modalOpen({
    Type: (): React.ReactElement => (
      <SelectPic
        cropping={false}
        action={async (image): Promise<void> => {
          // const uploadRes = await uploadHeadPortrait(
          //   `data:${image.mime};base64,${image.data}`
          // );
          // if (uploadRes) {}
          cb('test');
        }}
      />
    ),
    needBack: true,
    needClose: true
  });
};

export const startRecord = (): void => {
  AudioRecorder.onProgress = (data): void => {
    setRecordDuration(Number(data.currentTime.toFixed(1)));
  };
  AudioRecorder.prepareRecordingAtPath(audioPath, {
    SampleRate: 22050,
    Channels: 1,
    AudioQuality: 'High',
    AudioEncoding: 'aac'
  });
  AudioRecorder.startRecording();
};

const hideLoading = (needUnlink = true): void => {
  loading.hide();
  isUpload = false;
  if (needUnlink) {
    RNFS.unlink(audioPath);
  }
};

export const getAudioPreUploadInfo = async (path: string): Promise<void> => {
  const retryUpload = (): void => {
    if (tryUploadTime === MAX_TRY_UPLOAD_TIME) {
      tryUploadTime = 0;
      hideLoading(false);
      setShowRecord(false);
      // TODO: 更新音频时长，链接 recordDuration, audioUrl(本地音频链接) onAudioUploaded();
      // 如果失败了，也需要关闭录音弹框，这个时候需要本地音频
    } else {
      tryUploadTime += 1;
      setTimeout((): void => {
        getAudioPreUploadInfo(path);
      }, 1000);
    }
  };

  const { recordDuration } = state;
  const res = await AppApi.getAudioPreUploadInfo({
    audioType: 2,
    audioName: `correction-${new Date().getTime()}.mp3`
  });
  const { code, data } = res;
  if (code !== 0) {
    retryUpload();
    return;
  }

  const { ossPath, ossSTS, audioUrl } = data;
  const { accessKeyId, accessKeySecret, stsToken, endPoint, bucket } = ossSTS;
  AliyunOSS.initWithSecurityToken(
    stsToken,
    accessKeyId,
    accessKeySecret,
    endPoint
  );
  AliyunOSS.asyncUpload(bucket, ossPath, isIOS ? path : `file://${path}`)
    .then((): void => {
      hideLoading();
      setShowRecord(false);
      // TODO: 更新音频时长，链接 recordDuration, audioUrl onAudioUploaded();
    })
    .catch((): void => {
      retryUpload();
    });
};

export const startSendRecord = async (): Promise<void> => {
  const { recordDuration } = state;
  loading.show();
  isUpload = true;
  try {
    await AudioRecorder.stopRecording();
  } catch (error) {
    hideLoading();
    toolTipOpen({ desc: '说话时间太短' });
    return;
  }

  if (recordDuration < 1) {
    hideLoading();
    toolTipOpen({ desc: '说话时间太短' });
    return;
  }

  getAudioPreUploadInfo(audioPath);
};

export const handleBackButton = (): boolean => {
  const { recording } = state;
  if (recording) {
    setRecording(false);
    startSendRecord();
  } else if (!isUpload) {
    setShowRecord(false);
  }
  return true;
};

export const updateAudio = (sureAction: () => void): void => {
  modalOpen({
    Type: (): React.ReactElement => (
      <PortraitAlert
        title="更新语音"
        subTitle="即将保存并覆盖已有的答案"
        sureDesc="覆盖"
        sureAction={sureAction}
        cancelDesc="取消"
        cancelAction={(): void => {
          modalClose();
        }}
      />
    ),
    needBack: true
  });
};

export const editProblem = (sureAction: () => void): void => {
  modalOpen({
    Type: (): React.ReactElement => (
      <PortraitAlert
        title="修改练习题"
        subTitle="进入编辑状态，可以修改答错的问题，再次交给老师批改～"
        sureDesc="去修改"
        sureAction={sureAction}
        cancelDesc="取消"
        cancelAction={(): void => {
          modalClose();
        }}
      />
    ),
    needBack: true
  });
};
